//SPDX-FileCopyrightText: Copyright 2025-2025 深圳市同心圆网络有限公司
//SPDX-License-Identifier: GPL-3.0-only

package board_extdata_api_serv

import (
	"context"
	"time"

	"gitcode.com/eteam/api-server/dao"
	"gitcode.com/eteam/api-server/dao/board_dao"
	"gitcode.com/eteam/api-server/dao/user_dao"
	"gitcode.com/eteam/api-server/notice_serv"
	"gitcode.com/eteam/proto-gen-go.git/board_extdata_api"
	"gitcode.com/eteam/proto-gen-go.git/notices/notices_board"
	"github.com/google/uuid"
	"go.mongodb.org/mongo-driver/mongo"
)

type BoardExtDataApiImpl struct {
	board_extdata_api.UnimplementedBoardExtDataApiServer
}

func (apiImpl *BoardExtDataApiImpl) Add(ctx context.Context, req *board_extdata_api.AddRequest) (*board_extdata_api.AddResponse, error) {
	sessItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &board_extdata_api.AddResponse{
			Code:   board_extdata_api.AddResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	//检查权限
	memberItem, err := board_dao.MemberInfoDao.Get(ctx, req.BoardId, sessItem.UserId)
	if err != nil {
		return &board_extdata_api.AddResponse{
			Code:   board_extdata_api.AddResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}
	if !(memberItem.Admin) {
		return &board_extdata_api.AddResponse{
			Code:   board_extdata_api.AddResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}

	extDataId := uuid.NewString()
	nowTime := time.Now().UnixMilli()

	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(ctx, func(sessCtx mongo.SessionContext) (interface{}, error) {
		dbItem := &board_dao.ExtDataInfoDbItem{
			ExtDataId: extDataId,
			BoardId:   req.BoardId,
			BasicInfo: board_dao.BasicExtDataInfoDbItem{
				Name:        req.BasicInfo.Name,
				ExtDataType: req.BasicInfo.ExtDataType,
				ServUrl:     req.BasicInfo.ServUrl,
				AccessToken: req.BasicInfo.AccessToken,
			},
			CreateUserId: sessItem.UserId,
			CreateTime:   nowTime,
			UpdateUserId: sessItem.UserId,
			UpdateTime:   nowTime,
		}
		{
			realServType, ok := req.BasicInfo.ServType.(*board_extdata_api.BasicExtDataInfo_GitServType)
			if ok {
				dbItem.BasicInfo.GitServType = realServType.GitServType
			}
		}
		{
			realServType, ok := req.BasicInfo.ServType.(*board_extdata_api.BasicExtDataInfo_CrawlerServType)
			if ok {
				dbItem.BasicInfo.CrawlerServType = realServType.CrawlerServType
			}
		}
		{
			realServType, ok := req.BasicInfo.ServType.(*board_extdata_api.BasicExtDataInfo_MapServType)
			if ok {
				dbItem.BasicInfo.MapServType = realServType.MapServType
			}
		}
		err = board_dao.ExtDataInfoDao.Insert(sessCtx, dbItem)
		if err != nil {
			return nil, err
		}
		return &board_extdata_api.AddResponse{
			Code:      board_extdata_api.AddResponse_CODE_OK,
			ExtDataId: extDataId,
		}, nil
	})
	if err != nil {
		return nil, err
	}
	//发送通知
	go notice_serv.PublishToBoard(req.BoardId, &notices_board.ExtDataConfigChangeNotice{
		BoardId: req.BoardId,
	})
	return ret.(*board_extdata_api.AddResponse), nil
}

func (apiImpl *BoardExtDataApiImpl) Update(ctx context.Context, req *board_extdata_api.UpdateRequest) (*board_extdata_api.UpdateResponse, error) {
	sessItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &board_extdata_api.UpdateResponse{
			Code:   board_extdata_api.UpdateResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	//检查权限
	memberItem, err := board_dao.MemberInfoDao.Get(ctx, req.BoardId, sessItem.UserId)
	if err != nil {
		return &board_extdata_api.UpdateResponse{
			Code:   board_extdata_api.UpdateResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}
	if !(memberItem.Admin) {
		return &board_extdata_api.UpdateResponse{
			Code:   board_extdata_api.UpdateResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}
	//检查配置是否存在
	exist, err := board_dao.BoardInfoDao.Exist(ctx, req.BoardId)
	if err != nil {
		return nil, err
	}
	if !exist {
		return &board_extdata_api.UpdateResponse{
			Code:   board_extdata_api.UpdateResponse_CODE_NO_EXT_DATA_SERV,
			ErrMsg: "外部数据服务不存在",
		}, nil
	}

	nowTime := time.Now().UnixMilli()

	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(ctx, func(sessCtx mongo.SessionContext) (interface{}, error) {
		basicItem := &board_dao.BasicExtDataInfoDbItem{
			Name:        req.BasicInfo.Name,
			ExtDataType: req.BasicInfo.ExtDataType,
			ServUrl:     req.BasicInfo.ServUrl,
			AccessToken: req.BasicInfo.AccessToken,
		}
		{
			realServType, ok := req.BasicInfo.ServType.(*board_extdata_api.BasicExtDataInfo_GitServType)
			if ok {
				basicItem.GitServType = realServType.GitServType
			}
		}
		{
			realServType, ok := req.BasicInfo.ServType.(*board_extdata_api.BasicExtDataInfo_CrawlerServType)
			if ok {
				basicItem.CrawlerServType = realServType.CrawlerServType
			}
		}
		{
			realServType, ok := req.BasicInfo.ServType.(*board_extdata_api.BasicExtDataInfo_MapServType)
			if ok {
				basicItem.MapServType = realServType.MapServType
			}
		}
		err = board_dao.ExtDataInfoDao.Update(sessCtx, req.BoardId, req.ExtDataId, basicItem, sessItem.UserId, nowTime)
		if err != nil {
			return nil, err
		}
		return &board_extdata_api.UpdateResponse{
			Code: board_extdata_api.UpdateResponse_CODE_OK,
		}, nil
	})
	if err != nil {
		return nil, err
	}
	//发送通知
	go notice_serv.PublishToBoard(req.BoardId, &notices_board.ExtDataConfigChangeNotice{
		BoardId: req.BoardId,
	})
	return ret.(*board_extdata_api.UpdateResponse), nil
}

func (apiImpl *BoardExtDataApiImpl) Remove(ctx context.Context, req *board_extdata_api.RemoveRequest) (*board_extdata_api.RemoveResponse, error) {
	sessItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &board_extdata_api.RemoveResponse{
			Code:   board_extdata_api.RemoveResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	//检查权限
	memberItem, err := board_dao.MemberInfoDao.Get(ctx, req.BoardId, sessItem.UserId)
	if err != nil {
		return &board_extdata_api.RemoveResponse{
			Code:   board_extdata_api.RemoveResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}
	if !(memberItem.Admin) {
		return &board_extdata_api.RemoveResponse{
			Code:   board_extdata_api.RemoveResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}
	//检查配置是否存在
	exist, err := board_dao.BoardInfoDao.Exist(ctx, req.BoardId)
	if err != nil {
		return nil, err
	}
	if !exist {
		return &board_extdata_api.RemoveResponse{
			Code: board_extdata_api.RemoveResponse_CODE_OK,
		}, nil
	}

	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(ctx, func(sessCtx mongo.SessionContext) (interface{}, error) {
		err = board_dao.ExtDataInfoDao.Remove(sessCtx, req.BoardId, req.ExtDataId)
		if err != nil {
			return nil, err
		}
		return &board_extdata_api.RemoveResponse{
			Code: board_extdata_api.RemoveResponse_CODE_OK,
		}, nil
	})
	if err != nil {
		return nil, err
	}
	//发送通知
	go notice_serv.PublishToBoard(req.BoardId, &notices_board.ExtDataConfigChangeNotice{
		BoardId: req.BoardId,
	})
	return ret.(*board_extdata_api.RemoveResponse), nil
}

func (apiImpl *BoardExtDataApiImpl) List(ctx context.Context, req *board_extdata_api.ListRequest) (*board_extdata_api.ListResponse, error) {
	emptyList := []*board_extdata_api.ExtDataInfo{}

	sessItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &board_extdata_api.ListResponse{
			Code:        board_extdata_api.ListResponse_CODE_WRONG_SESSION,
			ErrMsg:      "会话不存在",
			ExtDataList: emptyList,
		}, nil
	}
	exist, err := board_dao.MemberInfoDao.Exist(ctx, req.BoardId, sessItem.UserId)
	if err != nil {
		return nil, err
	}
	if !exist {
		return &board_extdata_api.ListResponse{
			Code:        board_extdata_api.ListResponse_CODE_NO_PERMISSION,
			ErrMsg:      "没有权限",
			ExtDataList: emptyList,
		}, nil
	}
	extDataItemList, err := board_dao.ExtDataInfoDao.List(ctx, req.BoardId)
	if err != nil {
		return nil, err
	}
	extDataList, err := apiImpl.convertToExtDataList(ctx, extDataItemList)
	if err != nil {
		return nil, err
	}
	return &board_extdata_api.ListResponse{
		Code:        board_extdata_api.ListResponse_CODE_OK,
		ExtDataList: extDataList,
	}, nil
}

func (apiImpl *BoardExtDataApiImpl) Get(ctx context.Context, req *board_extdata_api.GetRequest) (*board_extdata_api.GetResponse, error) {
	emptyInfo := &board_extdata_api.ExtDataInfo{
		BasicInfo: &board_extdata_api.BasicExtDataInfo{
			ServType: &board_extdata_api.BasicExtDataInfo_CrawlerServType{},
		},
	}
	sessItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &board_extdata_api.GetResponse{
			Code:    board_extdata_api.GetResponse_CODE_WRONG_SESSION,
			ErrMsg:  "会话不存在",
			ExtData: emptyInfo,
		}, nil
	}
	exist, err := board_dao.MemberInfoDao.Exist(ctx, req.BoardId, sessItem.UserId)
	if err != nil {
		return nil, err
	}
	if !exist {
		return &board_extdata_api.GetResponse{
			Code:    board_extdata_api.GetResponse_CODE_NO_PERMISSION,
			ErrMsg:  "没有权限",
			ExtData: emptyInfo,
		}, nil
	}
	extDataItem, err := board_dao.ExtDataInfoDao.Get(ctx, req.BoardId, req.ExtDataId)
	if err != nil {
		return &board_extdata_api.GetResponse{
			Code:    board_extdata_api.GetResponse_CODE_NO_EXT_DATA_SERV,
			ErrMsg:  "外部数据服务不存在",
			ExtData: emptyInfo,
		}, nil
	}
	extDataList, err := apiImpl.convertToExtDataList(ctx, []*board_dao.ExtDataInfoDbItem{extDataItem})
	if err != nil {
		return nil, err
	}
	if len(extDataList) == 0 {
		return &board_extdata_api.GetResponse{
			Code:    board_extdata_api.GetResponse_CODE_NO_EXT_DATA_SERV,
			ErrMsg:  "外部数据服务不存在",
			ExtData: emptyInfo,
		}, nil
	}
	return &board_extdata_api.GetResponse{
		Code:    board_extdata_api.GetResponse_CODE_OK,
		ExtData: extDataList[0],
	}, nil
}

func (apiImpl *BoardExtDataApiImpl) convertToExtDataList(ctx context.Context, extDataItemList []*board_dao.ExtDataInfoDbItem) ([]*board_extdata_api.ExtDataInfo, error) {
	retList := []*board_extdata_api.ExtDataInfo{}
	//获取用户信息
	userIdList := []string{}
	for _, extDataItem := range extDataItemList {
		userIdList = append(userIdList, extDataItem.CreateUserId)
		userIdList = append(userIdList, extDataItem.UpdateUserId)
	}
	userItemList, err := user_dao.UserInfoDao.ListById(ctx, userIdList)
	if err != nil {
		return nil, err
	}
	userItemMap := map[string]*user_dao.UserInfoDbItem{}
	for _, userItem := range userItemList {
		userItemMap[userItem.UserId] = userItem
	}

	//生成结果
	for _, extDataItem := range extDataItemList {
		extData := extDataItem.ToExtDataInfo()
		createUser, ok := userItemMap[extDataItem.CreateUserId]
		if ok {
			extData.CreateDisplayName = createUser.BasicInfo.DisplayName
			extData.CreateLogoUri = createUser.BasicInfo.LogoUri
		}
		updateUser, ok := userItemMap[extDataItem.UpdateUserId]
		if ok {
			extData.UpdateDisplayName = updateUser.BasicInfo.DisplayName
			extData.UpdateLogoUri = updateUser.BasicInfo.LogoUri
		}
		retList = append(retList, extData)
	}
	return retList, nil
}
